<?php

namespace App\Repository;

use App\Repository\Wxpay\WxPayApi;
use App\Repository\Enum\OrderStatusEnum;
use App\Repository\Wxpay\Database\WxPayJsApiPay;
use App\Repository\Wxpay\Database\WxPayUnifiedOrder;
use Dingo\Api\Exception\StoreResourceFailedException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Class WxPayRepotitory
 * @package App\Repository
 */
class WxPayRepotitory
{
    /**
     * @var
     */
    private $orderId;
    /**
     * @var
     */
    private $orderNo;

    /**
     * WxPayRepotitory constructor.
     * @param $orderId
     */
    public function __construct( $orderId)
    {
        if (!$orderId){
            throw new SuspiciousOperationException('订单号不能为空', null, null, [], 400);
        }
        $this->orderId = $orderId;
    }

    /**
     * 支付主体方法
     * @return \Illuminate\Http\JsonResponse|void
     */
    public function pay()
    {
        $this->checkOrderValid();
        //检测库存量
        $orderRepository = new OrderRepository();
        $status = $orderRepository->checkOrderStock($this->orderId); //检测库存量
        if (!$status['pass']){
            return \Response::json($status);
        }
        return $this->makeWxPreOrder($status['orderPrice']);
    }

    /**
     * 订单号不存在
     * 订单号存在，但是订单号和用户不匹配
     * 订单的支付状态，未支付才能继续支付
     * @return bool
     */
    private function checkOrderValid()
    {
        $orderRepository = new OrderRepository();

        $order = $orderRepository->getOrderById($this->orderId);
        if (!$order){
            throw new NotFoundHttpException('订单不存在，请检测订单ID', null, 80000);
        }
        if ( !TokenRepository::isValidOperate($order->user_id) ){
            throw new StoreResourceFailedException('订单与用户不匹配', null, null, [], 10003);
        }
        if ($order->status != OrderStatusEnum::UNPAID){
            throw new SuspiciousOperationException('订单已支付', null, null, [], 80003);
        }
        $this->orderNo = $order->order_no;
        return true;
    }

    /**
     * 生成微信预订单[发送的参数是openid，order_no]
     * @param $totalPrice
     * @return array
     */
    private function makeWxPreOrder($totalPrice)
    {
        $openId = TokenRepository::getCurrentTokenVar('openid');
        if (!$openId){
            throw new StoreResourceFailedException('tokenss无效或者已过期', null, null, [] , 10001);
        }
        $wxOrderData = new WxPayUnifiedOrder();
        $wxOrderData->setOutTradeNo($this->orderNo);
        $wxOrderData->setTradeType('JSAPI');
        $wxOrderData->setTotalFee($totalPrice * 100);
        $wxOrderData->setBody('小帅商铺');
        $wxOrderData->setOpenid($openId);
        $wxOrderData->setNotifyUrl(env('WXNOTIFU_URL'));  //接受微信结果
        return $this->getPaySignature($wxOrderData);
    }

    /**
     * 获取支付签名
     * @param $wxOrderData
     * @return array
     */
    private function getPaySignature($wxOrderData)
    {
        $wxOrder = WxPayApi::unifiedOrder($wxOrderData);
        if ($wxOrder['return_code' != 'SUCCESS'] || $wxOrder['result_code'] != 'SUCCESS') {
            \Log::info('获取预支付订单失败', $wxOrder);
        }
        //更新prePay_id
        $this->recordPreOrder($wxOrder);
        return $this->sign($wxOrder);
    }

    /**
     * 保存prepay_id
     * @param $wxOrder
     */
    private function recordPreOrder($wxOrder)
    {
        $orderRepository = new OrderRepository();

        $orderRepository->updateDataById($this->orderId, $wxOrder['prepay_id ']);
    }

    /**
     * 生成签名及客户端所需参数
     * @param $wxOrder
     * @return array 客户端所需参数
     */
    private function sign($wxOrder)
    {
        $jsApiData = new WxPayJsApiPay();
        $jsApiData->setAppid(env('APPID'));
        $jsApiData->setTimeStamp((string) time());
        $rand = md5(time() . mt_rand(0, 99));
        $jsApiData->setNonceStr($rand);
        $jsApiData->setPackage('prepay_id='. $wxOrder['prepay_id']);
        $jsApiData->setSignType('md5');
        $sign = $jsApiData->makeSign();
        $rawValue = $jsApiData->getValues(); //返回原始数组
        $rawValue['paySign'] = $sign;

        unset($rawValue['appId']);
        return $rawValue;
    }
}